use std::{
    collections::HashMap,
    sync::{Arc, Mutex},
};

use bytes::Bytes;

#[derive(Debug, Clone)]
pub struct Db {
    state: Arc<Mutex<State>>,
}

// pub struct Shared {
//     state: Mutex<State>,
// }

#[derive(Debug, Clone)]
pub struct State {
    entries: HashMap<String, Entry>,
    next_id: u64,
}

impl Db {
    pub fn new() -> Self {
        let state = Arc::new(Mutex::new(State {
            entries: HashMap::new(),
            next_id: 0,
        }));

        Db { state }
    }

    pub fn get(&self, key: &str) -> Option<Bytes> {
        let state = self.state.lock().unwrap();
        state.entries.get(key).map(|e| e.data.clone())
    }

    pub fn set(&self, key: impl ToString, data: Bytes) -> Option<Bytes> {
        let mut state = self.state.lock().unwrap();
        let id = state.next_id;
        state.next_id += 1;

        let prev = state.entries.insert(key.to_string(), Entry { id, data });

        prev.map(|e| e.data)
    }
}

#[derive(Debug, Clone)]
pub struct Entry {
    id: u64,
    data: Bytes,
}
